/*
	How to compile: gcc -lrt -o shmConsumerMutex shmConsumerMutex.c 

	Description: We are going to access the "critical region" using a semaphore.
	The name of the semaphore is given by the creator: sem_mutex 

	We don't use a fixed key as in previous example. We generate the key.
	This process uses a known "key" to get access to a shared memory segment 
	allocated by some other process. Once we get a "memory segment identifier" we can 
	"attach it" to our virtual memory space in order to access it as normal memory, as a result 
	we'll have a memory pointer which can be used as an array name.

	Author: Hugo Mendez @ ITESM CCV Sep 2011
*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <semaphore.h>

#define SHMSZ 27
char SEM_NAME[]= "/mutexSem";

char *attachSharedMemorySegment(int *segment_id);

int main (int argc, const char * argv[]) {
	int segment_id;
	char *shm = attachSharedMemorySegment(&segment_id);

	//Let's read an string from the shared memory
	//Some process should have written something!
	printf("Let's open the semaphore\n");
	sem_t *sem_mutex;	//Variable to store the semaphore address
	//'mutex' is the name assigned to the semaphore by the creator process
	sem_mutex = sem_open(SEM_NAME, O_CREAT, 0644, 0);
	
	if( sem_mutex != SEM_FAILED ){
		//int semValue;
		//sem_getvalue(sem_mutex, &semValue);
		//printf("value: %d\n", semValue);
		//sem_post(sem_mutex);
		
		//sem_wait(sem_mutex);

		char *s;
		  for(s=shm;*s!='Z';s++)
		    {
		      sem_wait(sem_mutex);
		      putchar(*s);
		      sem_post(sem_mutex);
		    }
		//Write the '*', at location 0, our Creator program is waiting for
		shm[0]='*';
		sem_post(sem_mutex);
		sem_close(sem_mutex);
	}
	else{
		printf("Problems to open the semaphore!\n");
	}
	//Detach the memory segment
	shmdt(shm);

	return 0;  
}

char *attachSharedMemorySegment(int *segment_id){
	//Let's generate the "key", in the same way as the "creator" did it	
	key_t key; 
	key=ftok("shmCreatorMutex.c", '1');

	//Let's get access to the segment memory named "key"
	*segment_id = shmget(key, SHMSZ, 0666);

	//Check for problems
	if(*segment_id < 0){
	printf("Problemas al solicitar el segmento de memoria");
	exit(1);
	}
	printf("segment_id: %d\n", *segment_id);

	//Let's attach the memory segment to our address space in order to use it
	//Where in our address space are we going to attach it? Let Linux find it out
	char *shm;      //We need a byte pointer to have access to the shared memory segment
	shm = shmat(*segment_id, NULL, 0);
	return shm;

	//We can use:  return shmat(segment_id, NULL, 0);
}

